mod read;
mod write;
mod route;

use regex::Regex;
use lazy_static::lazy_static;

lazy_static! {
    static ref COB_SW_REGEX: Regex = Regex::new(r"([0-9a-fA-F]{8}) 32'h([0-9a-fA-F]{8}) cob_([0-9]+)_([0-9]+)_sw_([lrud]{2}|v|h)_([0-9]+)").unwrap();
    static ref COB_SEL_REGEX: Regex = Regex::new(r"([0-9a-fA-F]{8}) 32'h([0-9a-fA-F]{8}) cob_([0-9]+)_([0-9]+)_([a-z]+)_sel_([0-9]+)").unwrap();

    static ref TOB_HCTRL_REGEX: Regex = Regex::new("([0-9a-fA-F]{8}) 32'h([0-9a-fA-F]{8}) tob_([0-9]+)_([0-9]+)_hctrl_bank([0-9]+)_([0-9]+)").unwrap();
    static ref TOB_VCTRL_REGEX: Regex = Regex::new("([0-9a-fA-F]{8}) 32'h([0-9a-fA-F]{8}) tob_([0-9]+)_([0-9]+)_vctrl_bank([0-9]+)_([0-9]+)").unwrap();
    static ref TOB_BANK_SEL_REGEX: Regex = Regex::new("([0-9a-fA-F]{8}) 32'h([0-9a-fA-F]{8}) tob_([0-9]+)_([0-9]+)_bank_sel_([0-9]+)").unwrap();
}

pub use route::{route_track_path_to_track, route_track_to_track};
pub use read::read_controlbits;
pub use write::wirte_controlbits;

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_cob_sw_regex() {
        let s = "00000000 32'h9343AB32 cob_5_10_sw_ru_0";
        let captures = COB_SW_REGEX.captures(s).unwrap();
        assert_eq!(u32::from_str_radix(&captures[1], 16).unwrap(), 0);
        assert_eq!(u32::from_str_radix(&captures[2], 16).unwrap(), 0x9343AB32);
        assert_eq!(&captures[3], "5");
        assert_eq!(&captures[4], "10");
        assert_eq!(&captures[5], "ru");
        assert_eq!(&captures[6], "0");
    }

    #[test]
    fn test_cob_sel_regex() {
        let s = "00000000 32'h9003AB02 cob_0_2_down_sel_0";
        let captures = COB_SEL_REGEX.captures(s).unwrap();
        assert_eq!(u32::from_str_radix(&captures[1], 16).unwrap(), 0);
        assert_eq!(u32::from_str_radix(&captures[2], 16).unwrap(), 0x9003AB02);
        assert_eq!(&captures[3], "0");
        assert_eq!(&captures[4], "2");
        assert_eq!(&captures[5], "down");
        assert_eq!(&captures[6], "0");
    }

    #[test]
    fn test_tob_hctrl_regex() {
        let s = "00E0A72E 32'h90401350 tob_0_1_hctrl_bank1_3";
        let captures = TOB_HCTRL_REGEX.captures(s).unwrap();
        assert_eq!(u32::from_str_radix(&captures[1], 16).unwrap(), 0x00E0A72E);
        assert_eq!(u32::from_str_radix(&captures[2], 16).unwrap(), 0x90401350);
        assert_eq!(&captures[3], "0");
        assert_eq!(&captures[4], "1");
        assert_eq!(&captures[5], "1");
        assert_eq!(&captures[6], "3");
    }

    #[test]
    fn test_tob_vctrl_regex() {
        let s = "00FAC688 32'h9040137c tob_0_1_vctrl_bank0_6";
        let captures = TOB_VCTRL_REGEX.captures(s).unwrap();
        assert_eq!(u32::from_str_radix(&captures[1], 16).unwrap(), 0x00FAC688);
        assert_eq!(u32::from_str_radix(&captures[2], 16).unwrap(), 0x9040137c);
        assert_eq!(&captures[3], "0");
        assert_eq!(&captures[4], "1");
        assert_eq!(&captures[5], "0");
        assert_eq!(&captures[6], "6");
    }

    #[test]
    fn test_tob_bank_sel_regex() {
        let s = "03000808 32'h904013a8 tob_0_1_bank_sel_1";
        let captures = TOB_BANK_SEL_REGEX.captures(s).unwrap();
        assert_eq!(u32::from_str_radix(&captures[1], 16).unwrap(), 0x03000808);
        assert_eq!(u32::from_str_radix(&captures[2], 16).unwrap(), 0x904013a8);
        assert_eq!(&captures[3], "0");
        assert_eq!(&captures[4], "1");
        assert_eq!(&captures[5], "1");
    }

}